package com.bruce.tool.office.excel.util;

import com.bruce.tool.common.util.file.IOUtils;
import com.bruce.tool.office.excel.extend.ExcelToHtmlConverter;
import com.google.common.collect.Lists;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.w3c.dom.Document;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 功能 :
 *
 * @author : Bruce(刘正航) 8:20 PM 2018/12/8
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ContentUtils {

    private static final String TABLE_LINE_REGEX = "(<colgroup>[<col width=\"0-9>]+</colgroup>)";
    private static final String TABLE_COLUMN_REGEX = "(<col width=\"[0-9]+\">)";
    /**将Excel文件流转换成html字符串**/
    public static String transfer(InputStream in) throws ParserConfigurationException, TransformerException {

        if (!in.markSupported()) {
            in = new BufferedInputStream(in);
        }

        Document doc = process(in);

        return transfer(doc);
    }

    /**将Excel文件流转换成html字符串**/
    public static String transfer(Workbook workbook) throws ParserConfigurationException, TransformerException {

        Document doc = process(workbook);

        return transfer(doc);
    }

    /**转换成Document**/
    public static Document process(InputStream in) throws ParserConfigurationException {
        Workbook workbook = null;
        try {
            workbook = WorkBookUtils.create(in);
            if(null == workbook){ return null; }
            return process(workbook);
        } finally {
            IOUtils.closeQuietly(workbook,in);
        }
    }

    /**转换成Document**/
    public static Document process(Workbook workbook) throws ParserConfigurationException {
        //公式的自动计算
        workbook.getCreationHelper().createFormulaEvaluator().evaluateAll();
        ExcelToHtmlConverter converter = new ExcelToHtmlConverter(
                DocumentBuilderFactory
                        .newInstance()
                        .newDocumentBuilder()
                        .newDocument()
        );
        converter.setOutputColumnHeaders(false);
        converter.setOutputRowNumbers(false);
        removeUnActiveSheets(workbook);
        converter.processWorkbook(workbook);
        return converter.getDocument();
    }

    /**删除非激活的sheet,非激活状态的sheet不用转为html**/
    private static void removeUnActiveSheets(Workbook workbook) {
        int activeSheetIndex = workbook.getActiveSheetIndex();
        Iterator<Sheet> sheetIterator = workbook.sheetIterator();
        List<Integer> removeIndexs = Lists.newArrayList();
        while(sheetIterator.hasNext()){
            Sheet next = sheetIterator.next();
            int index = workbook.getSheetIndex(next);
            if(activeSheetIndex != index){
                removeIndexs.add(index);
            }
        }
        for (Integer index : removeIndexs){
            workbook.removeSheetAt(index);
        }
    }

    /**设置表格宽度,避免样式走样**/
    public static String setTableWidth(String content) {

        if(null == content || content.trim().length() == 0){ return null; }

        List<Integer> tableWidths = new ArrayList<>();

        gatherTableWidth(tableWidths,content);

        for (Integer tableWidth : tableWidths) {
            content = content.replaceFirst("<table class=\"t1\">", "<table class=\"t1\" width=\""+tableWidth+"\">");
        }

        return content;
    }

    /**搜集表宽度**/
    private static void gatherTableWidth(List<Integer> tableWithds, String content) {
        Pattern p1 = Pattern.compile(TABLE_LINE_REGEX);
        Matcher m1 = p1.matcher(content);
        List<String> colgroups = new ArrayList<>();
        while (m1.find()) {
            for (int i = 0; i < m1.groupCount(); i++) {
                String test1 = m1.group(i);
                colgroups.add(test1);
            }
        }

        for ( String colgroup : colgroups ) {
            Pattern p2 = Pattern.compile(TABLE_COLUMN_REGEX);
            Matcher m2 = p2.matcher(colgroup);
            int widths = 0;
            while (m2.find()) {
                String width = m2.group();
                width = width.replace("<col width=\"", "");
                width = width.replace("\">", "");
                widths += Integer.parseInt(width);
            }
            tableWithds.add(widths);
        }
    }

    private static String transfer(final Document doc) throws TransformerException {
        if (null == doc) { return null; }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DOMSource domSource = new DOMSource(doc);
        StreamResult streamResult = new StreamResult(baos);
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer serializer = tf.newTransformer();
        // TODO set encoding from a command argument
        serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        serializer.setOutputProperty(OutputKeys.INDENT, "no");
        serializer.setOutputProperty(OutputKeys.METHOD, "html");
        serializer.transform(domSource, streamResult);
        return new String(baos.toByteArray(), StandardCharsets.UTF_8);
    }
}
